跳到主要内容

Python 序列与集合类型

集合 Array

thislist = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
print(thislist)

# 使用构造函数来创建
thislist = list(("apple", "banana", "cherry")) # 请注意双括号

# 负的索引表示从后向前
print(thislist[-1])

# 索引范围(返回第三、第四、第五项)
print(thislist[2:5])

# 遍历列表
for x in thislist:
print(x)

# 检查是否存在
if "apple" in thislist:
print("Yes, 'apple' is in the fruits list")

# 列表长度
print(len(thislist))

# 添加项目
thislist.append("orange")

# 插入项目到指定位置
thislist.insert(1, "orange")

# 删除项目
thislist.remove("banana")

# 删除指定索引的元素(这个是弹出)
thislist.pop() # 如果未指定索引,则删除最后一项

# 关键字删除指定的索引
del thislist[0]

# 删除整个 list(注意:此时该 list 已经没有了,再调用会报错)
del thislist

# 清空 list
thislist.clear()

# 复制列表
list02 = thislist.copy()
# 或者直接创建时传入 list 类型也能复制
list02 = list(thislist)

# 合并
list1 = ["a", "b" , "c"]
list2 = [1, 2, 3]

list3 = list1 + list2
# 或者采用追加的方式
list1 = ["a", "b" , "c"]
list2 = [1, 2, 3]

for x in list2:
list1.append(x)

reverse() # 颠倒列表的顺序
sort() # 排序

解包的语法

在Python中,解包(Unpacking)是一种将可迭代对象(如元组、列表、字符串等)中的元素分配给变量的过程。解包允许你轻松地将可迭代对象中的值提取并分配给单独的变量,以便进一步处理。

以下是一些常见的解包示例:

  1. 元组解包

    my_tuple = (1, 2, 3)
    a, b, c = my_tuple # 解包元组
    print(a, b, c) # 输出: 1 2 3
  2. 列表解包

    my_list = [4, 5, 6]
    x, y, z = my_list # 解包列表
    print(x, y, z) # 输出: 4 5 6
  3. 字符串解包

    my_string = "hello"
    a, b, c, d, e = my_string # 解包字符串
    print(a, b, c, d, e) # 输出: h e l l o
  4. 多重赋值和交换值

    a, b = 1, 2
    a, b = b, a # 交换变量值的常见技巧
    print(a, b) # 输出: 2 1
  5. *运算符解包: 当你不知道可迭代对象中有多少个元素时,可以使用 * 运算符进行扩展解包。

    my_list = [1, 2, 3, 4, 5]
    a, *rest = my_list # 使用 * 进行扩展解包
    print(a) # 输出: 1
    print(rest) # 输出: [2, 3, 4, 5]
  6. 迭代解包: 在迭代器或生成器中使用解包来逐个访问元素。

    iterable = [(1, 'one'), (2, 'two'), (3, 'three')]
    for number, name in iterable:
    print(f"{name} is {number}")

解包是Python中的一个强大而灵活的特性,它可以简化代码并使你的代码更具可读性。不仅可以用于分配多个变量,还可以用于快速访问数据结构的元素。

List 的推导

列表推导 (List Comprehension)

列表推导是一种简洁的方式来创建列表。基本格式如下:

[expression for item in iterable]

下面给个例子

# 首先定义了一个字典推导
char_to_int = {char: i for i, char in enumerate(nums)}
label = torch.tensor([char_to_int[char]
for char in label_str], dtype=torch.long) # 转换为整数张量

这里遍历字符串 label_str 中的每个字符 char,并使用字典 char_to_int 将其转换为整数。结果是一个整数列表,然后使用 torch.tensor 将其转换为一个 PyTorch 张量。 例如,如果 char_to_int = {'a': 0, 'b': 1, 'c': 2} 并且 label_str = 'abc',那么结果列表将是 [0, 1, 2]

字典的推导

字典推导 (Dictionary Comprehension) 字典推导是一种简洁的方式来创建字典。基本格式如下:

{key: value for item in iterable}

在给定的代码中:

char_to_int = {char: i for i, char in enumerate(nums)}

这里使用 enumerate(nums) 来遍历 nums 列表的索引和值。对于每个字符 char,它的索引 i 作为值,而 char 作为键。 例如,如果 nums = ['a', 'b', 'c'],那么 char_to_int 将会是 {'a': 0, 'b': 1, 'c': 2}

简单的例子:

  1. 使用字典推导从列表中创建一个字典,其中列表的值作为键,值的平方作为值:

    nums = [1, 2, 3, 4]
    square_dict = {num: num**2 for num in nums}
    print(square_dict) # 输出: {1: 1, 2: 4, 3: 9, 4: 16}
  2. 使用列表推导从字符串中创建一个列表,其中每个字符重复两次:

    s = "abc"
    repeated_list = [char*2 for char in s]
    print(repeated_list) # 输出: ['aa', 'bb', 'cc']

结合字典推导和列表推导

以下是一个结合字典推导和列表推导的例子:

场景:假设我们有一个字典,其中键是人的名字,值是他们的年龄。我们想要创建一个新的字典,其中键是年龄大于20岁的人的名字,值是他们的爱好列表。

# 原始字典
people = {
"Alice": 25,
"Bob": 18,
"Charlie": 22,
"David": 19
}

# 每个人的爱好列表
hobbies = {
"Alice": ["reading", "swimming"],
"Bob": ["cycling"],
"Charlie": ["hiking", "photography"],
"David": ["drawing"]
}

# 使用字典推导和列表推导组合
result = {name: [hobby.upper() for hobby in hobbies[name]] for name, age in people.items() if age > 20}

print(result)

输出

{'Alice': ['READING', 'SWIMMING'], 'Charlie': ['HIKING', 'PHOTOGRAPHY']}

在这个例子中,我们首先使用外部的字典推导来过滤出年龄大于20岁的人。然后,对于每个选定的人,我们使用列表推导来获取他们的爱好列表,并将每个爱好转换为大写。最终的结果是一个新的字典,其中键是年龄大于20岁的人的名字,值是他们的大写爱好列表。

元组 Tuple

元组是有序且不可更改的集合。在 Python 中,元组是用圆括号编写的

thistuple = ("apple", "banana", "cherry")

# 使用构造函数来创建
thistuple = tuple(("apple", "banana", "cherry")) # 请注意双括号

# 其实操作和 list 大同小异
print(thistuple[1])

# 更改元组值(虽然无法直接修改,但是可以先转成 list 再转成 tuple)
x = ("apple", "banana", "cherry")
y = list(x)
y[1] = "kiwi"
x = tuple(y)

# 创建有一个项目的元组
# 如需创建仅包含一个项目的元组,必须在该项目后添加一个逗号,否则 Python 无法将变量识别为元组。
thistuple = ("apple",)
print(type(thistuple))

#不是元组
thistuple = ("apple")
print(type(thistuple))

元组和列表的区别

在Python中,元组(tuple)和列表(list)都是用来存储一组数据的容器,但它们之间有一些关键的区别:

  1. 可变性(Mutability)

    • 列表(List)是可变的(Mutable)。这意味着你可以在创建列表后添加、删除或修改其中的元素。
    • 元组(Tuple)是不可变的(Immutable)。一旦创建了元组,就无法更改其中的元素。
  2. 语法表示

    • 列表使用方括号 [] 表示,元素之间用逗号 , 分隔。
    • 元组使用圆括号 () 表示,元素之间同样用逗号 , 分隔。注意,如果元组只包含一个元素,需要在元素后面加上逗号,以区分它与表达式中的括号。

    示例:

    my_list = [1, 2, 3]  # 这是一个列表
    my_tuple = (1, 2, 3) # 这是一个元组
    single_element_tuple = (4,) # 包含一个元素的元组
  3. 性能

    • 由于元组是不可变的,它们的访问速度通常比列表快。这使得元组成为适合存储不会改变的数据的好选择。
    • 列表的可变性会导致一些额外的开销,因此在某些情况下,元组可能比列表更高效。
  4. 用途

    • 通常情况下,列表更适合用于存储和操作一系列数据,特别是当需要动态添加或删除元素时。
    • 元组通常用于表示不可变的数据集合,例如函数的多返回值、字典的键等。另外,元组也可以用作字典的键,因为它们是不可变的。

    示例:

    # 使用列表来表示一组学生的分数
    scores = [85, 90, 78, 92]

    # 使用元组来表示一个坐标点
    point = (3, 4)

    # 元组作为字典的键
    coordinates = {(0, 0): "原点", (1, 1): "一一点"}

元组的使用场景

元组(tuple)在以下情况下通常是一个合适的选择:

  1. 不可变性重要: 当你希望数据集合在创建后不被修改时,元组是一个合适的选择。元组的不可变性意味着一旦创建,它们不能被修改,这可以防止无意中或恶意地更改数据。

  2. 多个值的有序组合: 元组通常用于表示多个相关的值的组合,例如坐标、日期时间、点的坐标等。在这些情况下,元组提供了一个方便的方式来组织和访问这些值。

  3. 函数的多返回值: 当一个函数需要返回多个值时,通常使用元组。元组可以将多个值打包成一个返回值,然后在调用函数的地方解包这些值。

    def get_user_info(user_id):
    # 假设从数据库中获取用户信息
    user_data = fetch_user_data(user_id)
    return user_data.name, user_data.email
  4. 作为字典的键: 字典的键必须是不可变的,因此元组可以用作字典的键,特别是当需要将多个值组合成一个键时。

    user_info = {('John', 'Doe'): 12345, ('Alice', 'Smith'): 67890}
  5. 解包和迭代: 在迭代或解包值时,元组非常有用。例如,可以使用元组来同时迭代多个值,或将函数的多个参数打包成一个元组。

    for x, y in coordinates:
    print(f"X: {x}, Y: {y}")

总的来说,元组在需要不可变性、有序组合、多返回值或作为字典键时非常有用。它们提供了一种有效的数据结构来管理这些情况下的数据。如果你需要一个可变的数据结构,通常应该选择列表而不是元组。

集合 Set

集合是无序和无索引的集合。在 Python 中,集合用花括号编写。

thisset = {"apple", "banana", "cherry"}
# 构造方法创建
thisset = set(("apple", "banana", "cherry")) # 请留意这个双括号

# 添加项目
# 要将一个项添加到集合,请使用 add() 方法。
# 要向集合中添加多个项目,请使用 update() 方法。
thisset.add("orange")
thisset.update(["orange", "mango", "grapes"])

# 合并两个集合
set1 = {"a", "b" , "c"}
set2 = {1, 2, 3}

set3 = set1.union(set2)

# 或者使用 update 合并
set1 = {"a", "b" , "c"}
set2 = {1, 2, 3}

set1.update(set2)

字典 Dict

就是 Hash 类型

thisdict =	{
"brand": "Porsche",
"model": "911",
"year": 1963
}

# 获取 "model" 键的值:
x = thisdict["model"]

# 或者使用 get 方法
x = thisdict.get("model")

# 更改值
thisdict["year"] = 2019

# 遍历键
for x in thisdict:
print(x)
# 遍历值
for x in thisdict.values():
print(x)
# 遍历键和值
for x, y in thisdict.items():
print(x, y)

# 添加项目
thisdict["color"] = "red"

# 删除项目
thisdict.pop("model")

# 复制
dict02 = thisdict.copy()
# 或
dict02 = dict(thisdict)

# 嵌套字典
family = {
"child1" : {
"name" : "Phoebe Adele",
"year" : 2002
},
"child2" : {
"name" : "Jennifer Katharine",
"year" : 1996
},
"child3" : {
"name" : "Rory John",
"year" : 1999
}
}
# 或者
child1 = {
"name" : "Phoebe Adele",
"year" : 2002
}
child2 = {
"name" : "Jennifer Katharine",
"year" : 1996
}
child3 = {
"name" : "Rory John",
"year" : 1999
}

family = {
"child1" : child1,
"child2" : child2,
"child3" : child3
}

迭代器

迭代器是实现迭代器协议的对象,它包含方法 __iter__()__next__()

数组对象(列表、元组、字典和集合)都有用于获取迭代器的 iter() 方法

mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)

print(next(myit))
print(next(myit))
print(next(myit))

# 字符串也是可迭代的对象
mystr = "banana"
myit = iter(mystr)

print(next(myit))
print(next(myit))


# 创建迭代器
class MyNumbers:
def __iter__(self):
self.a = 1
return self

def __next__(self):
x = self.a
self.a += 1
return x

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))


# 为了防止迭代循环下去可以使用 StopIteration
# 在 __next__() 方法中,如果迭代完成指定的次数,可以添加一个终止条件来引发错误:
# 在 20 个迭代之后停止:
class MyNumbers:
def __iter__(self):
self.a = 1
return self

def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)

for x in myiter:
print(x)